/**
 *  Copyright (c)  2011-2020 Panguso, Inc.
 *  All rights reserved.
 *
 *  This software is the confidential and proprietary information of Panguso, 
 *  Inc. ("Confidential Information"). You shall not
 *  disclose such Confidential Information and shall use it only in
 *  accordance with the terms of the license agreement you entered into with Panguso.
 */
package cn.edu.thu.log.xes;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.regex.Pattern;

import org.deckfour.xes.classification.XEventAttributeClassifier;
import org.deckfour.xes.extension.XExtension;
import org.deckfour.xes.extension.XExtensionManager;
import org.deckfour.xes.extension.std.XConceptExtension;
import org.deckfour.xes.extension.std.XTimeExtension;
import org.deckfour.xes.factory.XFactory;
import org.deckfour.xes.factory.XFactoryRegistry;
import org.deckfour.xes.info.XLogInfo;
import org.deckfour.xes.info.XLogInfoFactory;
import org.deckfour.xes.model.XAttribute;
import org.deckfour.xes.model.XAttributeMap;
import org.deckfour.xes.model.XEvent;
import org.deckfour.xes.model.XLog;
import org.deckfour.xes.model.XTrace;
import org.deckfour.xes.model.impl.XAttributeLiteralImpl;
import org.deckfour.xes.out.XesXmlSerializer;
import org.jdom.Document;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import storage.dbhelper.LogBodyHelper;
import storage.dbhelper.LogHeadHelper;
import storage.dbobject.DbLogHead;
import storage.dbhelper.XESHelper;
import storage.dbobject.DbLogBody;
import cn.edu.thu.log.clean.NoiseIdentify1;
import cn.edu.thu.log.filter.logfilter.LogFilter;
import storage.dbobject.DbXES;
import cn.edu.thu.log.read.LogBufferModified;
import cn.edu.thu.log.read.LogConfig;
import cn.edu.thu.log.read.LogFilesReader;
import cn.edu.thu.log.util.Format;
import cn.edu.thu.log.util.PanGuConstants;
import cn.edu.thu.log.web.service.LogCleanConfigReadService;
import cn.edu.thu.log.web.service.PropertiesReaderServices;
import cn.edu.thu.log.web.service.WebConfigReadService;
import cn.edu.thu.log.web.service.XESConvertService;
import cn.edu.thu.log.web.service.impl.LogCleanConfigReadServiceImpl;
import cn.edu.thu.log.web.service.impl.PropertiesReaderServicesImpl;
import cn.edu.thu.log.web.service.impl.WebConfigReadServiceImpl;
import cn.edu.thu.log.web.service.impl.XESConvertServiceImp;

/**
 * class XES Writer. based on configuration, write logs from file to one XES
 * file
 * 
 * @author meng
 * 
 */
public class XESConvertormodified {
	// activePGIDList

	private String classify;
	// List<String> activeList;
	// int fitEvent = 0;
	private int clock = 0;
	private final String branch11 = "-bn";
	private int numOfEvent = 0;
	private int oldNumOfEvent = 0;
	private int totalEvent = 0;
	private int xesBranch2 = 0;
	private String currentTimeString;
	/**
	 * factory
	 */
	private static XFactory factory;
	public static XFactory getFactory() {
		return factory;
	}
	public static void setFactory(XFactory factory) {
		XESConvertormodified.factory = factory;
	}

	private XLog logReplace;
	private WebConfigReadService xesConfig;
	private String filePath;
	private String timestampTag;
	private String resultFilePath;
	private XLog log;
	/**
	 * map of latest trace from each caseID
	 */
	private Hashtable<String, XTrace> caseTraceMap;
	private Hashtable<String, Integer> caseBranchMap;
	// from logContent
	private ArrayList<String> cateList;
	private LogConfig logConfig;
	private XEventAttributeClassifier classifier;
	private XExtensionManager extensionManager;
	// for logBuffer clean and noise detect
	private LogBufferModified testLogBuffer = new LogBufferModified();
	// log format
	
	// caseIDTagList
	private ArrayList<String> caseIDTagList;
	// LogHeadTag
	private ArrayList<String> logHeadTagList;
	// AvtivityList
	private ArrayList<String> activityTagList;
	private ArrayList<String> activityAbbreList;
	private ArrayList<String> activityLocList;
	private Hashtable<String, String> activityNameLocMap;
	// AttributeList
	private ArrayList<String> attributeTagList;
	private ArrayList<String> attributeAbbreList;
	private ArrayList<String> attributeLocList;
	private String sessionid;
	/**
	 * 
	 * @return
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	public String getSessionID() {
		return sessionid;
	}
	/**
	 * 
	 * @param sessionID
	 * SessionID
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	public void setSessionID(String sessionID) {
		this.sessionid = sessionID;
	}

	// ArrayList<String> attributeLocList;
	private Hashtable<String, String> tagAbbreLocMap;
	private String classifyTags;
	// setupTimeStamp
	private String timeStampIndentifier; // dm
	private int timeStampLoc = 0;
	// caseIDLocation
	private ArrayList<Integer> caseIDLocList;
	/**
	 * noise Identifier
	 */
	private NoiseIdentify1 noiseidentify1;
	private LogCleanConfigReadService readLogCleanConfigService;

	/**
	 * Constructor
	 * 
	 * @param xesConfig
	 *            Reader to read configFile
	 * @param filePath
	 *            the file to save the result log
	 * @param sessionID
	 *            the file to save the result log
	 */
	public XESConvertormodified(WebConfigReadService xesConfig, String filePath,
			String sessionID) {
		this.sessionid = sessionID;
		factory = XFactoryRegistry.instance().currentDefault();
		// XFactoryRegistry.instance().setSizeOfShadowMap(10);
		this.xesConfig = xesConfig;
		this.filePath = filePath;
		logConfig = new LogConfig();

		noiseidentify1 = new NoiseIdentify1();
		readLogCleanConfigService = LogCleanConfigReadServiceImpl
				.instance();

	}
	/**
	 * 
	 * @param xesConfig
	 * xesConfig
	 * @param filePath
	 * filePath
	 * @param classify
	 * classify
	 * @param sessionID
	 * SessionID
	 */
	public XESConvertormodified(WebConfigReadService xesConfig, String filePath,
			String classify, String sessionID) {
		this.sessionid = sessionID;
		factory = XFactoryRegistry.instance().currentDefault();
		// XFactoryRegistry.instance().setSizeOfShadowMap(10);
		this.xesConfig = xesConfig;
		this.filePath = filePath;
		logConfig = new LogConfig();

		noiseidentify1 = new NoiseIdentify1();
		readLogCleanConfigService = LogCleanConfigReadServiceImpl
				.instance();
		this.classify = classify;
	}

	/**
	 * entry function for write
	 * 
	 * @param resultfilePath
	 *            file need to be read	
	 * @throws Exception
	 * Exception
	 * @return
	 */
	public void write(String resultfilePath) throws Exception {

		// initialize
		this.resultFilePath = resultfilePath;
		LogFilesReader logfilesReader = new LogFilesReader();
		cateList = new ArrayList<String>();
		cateList = logfilesReader.getCateList(filePath);
		File readfile = new File(filePath);
		log = factory.createLog();
		logReplace = factory.createLog();
		XESConvertorMonitor.instance().setNumOfEvent(0);

		caseTraceMap = new Hashtable<String, XTrace>();
		caseBranchMap = new Hashtable<String, Integer>();

		// setup avtivityClassifier
		setupClassifier();
		// setup extensions
		setupExtensions();
		// setup global attributes
		setupGlobalAttributes();
		// initialize the config and logHead format
		initConfig();

		// read File or Directory
		// Timer timer = new Timer();
		// timer.start();
		readFile(readfile);

		System.out.print("\nfinish ReadFile\n");
		System.out.println("log size:" + log.size());
		// split the remaining log
		splitFinalLog();

		// write remaining log and logReplace
		System.out.print("\nsize of logReplace before write to XES:"
				+ XESConvertorMonitor.instance().getNumOfEvent());
		// XESConvertorMonitor.instance().deleteNotFit(log);
		// XESConvertorMonitor.instance().deleteNotFit(logReplace);
		writeToXES(log);
		writeToXES(logReplace);
		return;
	}

	/**
	 * set up classifier for log
	 */
	private void setupClassifier() {
		String[] keys = { XConceptExtension.KEY_NAME };
		classifier = new XEventAttributeClassifier("activity classifier", keys);
		log.getClassifiers().add(classifier);

	}

	/**
	 * 
	 * 
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	private void setupExtensions() {
		XExtension timeExtension = XTimeExtension.instance();
		XExtension conceptExtension = XConceptExtension.instance();
		log.getExtensions().add(timeExtension);
		log.getExtensions().add(conceptExtension);

	}

	/**
	 * 
	 * 
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	private void setupGlobalAttributes() {

		XAttribute attributeConcept = factory.createAttributeLiteral(
				XConceptExtension.KEY_NAME, "name", null);
		log.getGlobalEventAttributes().add(attributeConcept);
		XAttribute attributeTime = factory.createAttributeLiteral(
				XTimeExtension.KEY_TIMESTAMP, "time", null);
		log.getGlobalEventAttributes().add(attributeTime);

		log.getGlobalTraceAttributes().add(attributeConcept);
	}

	/**
	 * 
	 * @throws Exception
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	private void initConfig() throws Exception {
		// activeList = Temp.getActivePGID();
		// logConfig.config(PanGuConstants.LOGREAD_CONFIGFILE);
		logConfig.config();		

		// setUpcaseIDList
		caseIDTagList = xesConfig.getPattern().getCaseIDList(); // dm
		System.out.println("caseIDTagList here:" + caseIDTagList);
		// mainCase
		String mainCase = xesConfig.getPattern().getMainCaseID(); // dm
		if (caseIDTagList.isEmpty()) {
			caseIDTagList.add(mainCase);
		}
		System.out.println("caseIDTagList:" + caseIDTagList);
		tagAbbreLocMap = new Hashtable<String, String>();	
		// setAvtivityList
		activityTagList = xesConfig.getPattern().getActivityList(); // dm
		activityAbbreList = new ArrayList<String>();
		setActivityAbbre(activityTagList, activityAbbreList);

		classifyTags = xesConfig.getPattern().getClassifytag();
		readLogCleanConfigService.setClassifyTags(classifyTags);
		System.out.println("classifyTags:" + classifyTags);

		// setAttributeList
		attributeTagList = xesConfig.getPattern().getAttributeList(); // dm
		// System.out.println("attributeTagList:"+attributeTagList);
		attributeAbbreList = new ArrayList<String>();
		attributeLocList = new ArrayList<String>();
		setActivityAbbre(attributeTagList, attributeAbbreList);
		System.out.println("attributeTagList:" + attributeTagList);
		System.out.println("attributeAbbreList:" + attributeAbbreList);

		// setupTimeStamp and timeStamp location
		timeStampIndentifier = xesConfig.getPattern().getTimeStamp(); // dm
		LogBodyHelper logBodyH =new LogBodyHelper();
		// setup caseID and caseID location
		List<DbLogBody> logBodys = logBodyH.getLogBodys(DbLogBody.CL_NAME,
				timeStampIndentifier);
		timestampTag="ts";
		if(logBodys!= null && logBodys.size() > 0 ) {
			timestampTag = logBodys.get(0).getAbbreviation();
		}	
	}

	/**
	 * reader for file/Directory
	 * 
	 * @param readfile
	 *            log file
	 * @param logUI
	 *            GUI for test
	 */
	private void readFile(File readfile) {
		if (!readfile.isDirectory()) {
			// 如果选择了日志清洗规则，则读取规则生成tree
			if (readLogCleanConfigService.getNoiseflag() == 1) {
				noiseidentify1
						.readNoiseIdetifyConfigFile(readLogCleanConfigService);
			}
			readFileContent(readfile);
		} else if (readfile.isDirectory()) {
			File[] fileList = readfile.listFiles();
			for (int i = 0; i < fileList.length; i++) {
				File editfile = fileList[i];
				if (!editfile.isDirectory()) {
					readFileContent(editfile);

				} else if (editfile.isDirectory()) {
					readFile(editfile);
				}
			}
		}
	}

	/**
	 * read content of one file
	 * 
	 * @param file
	 *            log file
	 */
	private void readFileContent(File file) {
		Timer timer = new Timer();

		String logHeadContent = "";
		String logBodyContent = "";
		LogBufferModified logBuffer;
		// XES event
		XEvent event;
		// read each log Record
		BufferedReader reader;
		// String recordTemp;
		String record;
		try {
			FileInputStream fr = new FileInputStream(file);
			InputStreamReader is = new InputStreamReader(fr, "UTF-8");
			reader = new BufferedReader(is);
			while ((record = reader.readLine()) != null) {
				event = factory.createEvent();
				logBuffer = new LogBufferModified();
				String temprecord = record;
				
				String [] strs1 = temprecord.split("\\?");
				String tempstring ="";
				if(strs1.length < 2 ) {
					continue;
				} else  {
					for( int i= 1 ;   i < strs1.length ; i ++ ) {
						tempstring += strs1[i];
					}
				}
				String[] tempkeyvalues = tempstring.split("&utm");
				for(int i = 0 ; i < tempkeyvalues.length ; i ++ ) {
					String[] tempkeyss = tempkeyvalues[i].split("=");
					String values = "";
					String keys ="";
					if(tempkeyss.length < 2 ) {
						continue;
					} else {
						keys = tempkeyss[0];
						for( int j = 1 ; j < tempkeyss.length ; j ++   ) {
							values += tempkeyss[j];
						}
						logBuffer.addkeyvalue(keys, values);
					}
					
				}

				/*
				 * ---set up logBuffer and put it into event-------
				 */				
				logBuffer.setLogPath(file.getAbsolutePath());
			

				/**
				 * noise test and clean test for logBuffer
				 */
				setTestLogBuffer(logBuffer);
	

				if (readLogCleanConfigService.getNoiseflag() == 1) {
					// noiseidentify1.readNoiseIdetifyConfigFile(readLogCleanConfigService);
					if (noiseidentify1.logNoise(logBuffer)) {
						continue;
					} 
				} else if (!readLogCleanConfigService.getClassifyTags()
						.equals("")) {

					LogFilter logfilter = new LogFilter();
					logfilter.setClassifyTags(classifyTags);
					logfilter.filter(logBuffer);
				}

				// set timeStamp(content) to logBuffer
				String timeStampContent = logBuffer.getContent(timestampTag);
				if(timeStampContent == null) {
					continue;
				}
				logBuffer.setTimeStamp(timeStampContent);

				// set caseID tag and content to LogBuffer
				ArrayList<String> caseIDContentList = new ArrayList<String>();
				String logCaseIDString = new String("");
				for (int i = 0; i < caseIDTagList.size(); i++) {
					String caseIDTag = caseIDTagList.get(i);
					if (logBuffer.getContent(caseIDTag) != null) {
						String caseIDContent = logBuffer.getContent(caseIDTag);
						caseIDContentList.add(caseIDContent);
						logCaseIDString += caseIDContent + ",";
					} else {
						caseIDContentList.add("NA");
						logCaseIDString += "NA" + ",";
					}

				}
				logBuffer.setCaseIDList(caseIDContentList);
				logBuffer.setCaseIDString(logCaseIDString);

				// set activityContent to LogBuffer
				ArrayList<Object> activityIDContentList = new ArrayList<Object>();
				for (int l = 0; l < activityAbbreList.size(); l++) {
					String activityAbbre = activityAbbreList.get(l);
					if(logBuffer.getContent(activityAbbre) != null ) {
						activityIDContentList.add(activityAbbre + ":"
								+ logBuffer.getContent(activityAbbre));
					}
					
				}

				for (int l = 0; l < activityTagList.size(); l++) {
					if(logBuffer.getContent(activityAbbreList.get(l)) != null ) {
						Object activityL = logBuffer.getContent(activityAbbreList.get(l));
						if (activityL != null) {
							if (activityL.toString().length() > 0) {
								activityIDContentList.add(activityTagList.get(l)+ ":" + activityL);
							} else {
								activityIDContentList.add("NA");
							}
						}
					}					 else {
						activityIDContentList.add("NA");
					}
				}
				if (activityIDContentList.size() == 0) {

					continue; // dm
				}
				logBuffer.setActivityIDContentList(activityIDContentList);

				// set attributeLiat to LogBuffer
				Hashtable<String, String> attributeIDContenMap = new Hashtable<String, String>(); // <TagName,TagContent>
				for (int l = 0; l < attributeAbbreList.size(); l++) {
					String attributeAbbre = attributeAbbreList.get(l);
					String tagName = tagAbbreLocMap.get(attributeAbbre);
					String bodyContent = logBuffer.getContent(tagName);
					if (bodyContent != null) {
						if (bodyContent.toString().length() > 0) {
							attributeIDContenMap.put(tagName, bodyContent);
						} else {
							attributeIDContenMap.put(tagName, "NA");
						}
						// attributeIDContenMap.put(tagName, bodyContent);
					} else {
						attributeIDContenMap.put(tagName, "NA");
					}
				}

				logBuffer.setAttributeIDContentMap(attributeIDContenMap);

				// set logBuffer to event

				writeEvent(event, logBuffer);

				/*
				 * ---put event to trace,trace to log-------
				 */

				putEventToLog(logBuffer, event);
			}
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * set up the activity tag in each logBuffer
	 * 
	 * @param activityIDTagList
	 *            the activities' tags eat up by user
	 * @param logTagList
	 *            the tag list read from config reader
	 * @return the list of location of activityTag in whole tagList
	 */
	private void setActivityAbbre(ArrayList<String> actvityList,
			ArrayList<String> activityAbbreList1) {

		LogBodyHelper logBodyH = new LogBodyHelper();
		for (int i = 0; i < actvityList.size(); i++) {
			String activityName = actvityList.get(i);
			List<DbLogBody> logBodys = logBodyH.getLogBodys(DbLogBody.CL_NAME,
					activityName);

			if (logBodys.size() != 0) { // avtivity belong to logBody
				DbLogBody logBody = logBodys.get(0);
				String abbre = logBody.getAbbreviation();
				activityAbbreList1.add(abbre);
				if (!tagAbbreLocMap.contains(abbre)) {
					tagAbbreLocMap.put(abbre, activityName);
				}
			}
			
		}
		return;
	}

	/**
	 * write activities,logPath,caseID to event
	 * 
	 * @param event
	 * @param logBuffer
	 */
	private void writeEvent(XEvent event, LogBufferModified logBuffer) {

		// get content of this event
		ArrayList<Object> logActivityContents = logBuffer
				.getActivityIDContentList();
		// create a event
		XAttributeMap attributeMap = factory.createAttributeMap();

		// put the log tags as attributes to attributeMap
		String activityVal = "";
		for (int i = 0; i < logActivityContents.size(); i++) {
			if (logActivityContents.get(i) != null) {
				String logActivityL = logActivityContents.get(i).toString(); // ww
				if (i == 0) {
					activityVal = logActivityL;
				} else {
					activityVal = activityVal + "," + logActivityL;
				}
			}
		}
		if (activityVal.length() > 0) {
			XAttribute attribute = factory.createAttributeLiteral(
					XConceptExtension.KEY_NAME, activityVal, null);
			attributeMap.put(XConceptExtension.KEY_NAME, attribute);

		} else {
			XAttribute attribute = factory.createAttributeLiteral(
					XConceptExtension.KEY_NAME, "NA", null);
			attributeMap.put(XConceptExtension.KEY_NAME, attribute);
		}

		// get attribute of this event
		Hashtable<String, String> logAttibuteContentMap = logBuffer
				.getAttributeIDContentMap();
		Enumeration keyEnumer = logAttibuteContentMap.keys();
		// put the log tags as attributes to attributeMap

		while (keyEnumer.hasMoreElements()) {
			String attributeTagName = keyEnumer.nextElement().toString();
			String attributeContent = logAttibuteContentMap
					.get(attributeTagName);
			if (attributeContent != null && attributeContent.length() > 0) {
				XAttribute attribute = factory.createAttributeLiteral(
						attributeTagName, attributeContent, null);
				attributeMap.put(attributeTagName, attribute);
			} else { // content==null or content=""
				XAttribute attribute = factory.createAttributeLiteral(
						attributeTagName, "NA", null);
				attributeMap.put(attributeTagName, attribute);
			}

		}

		// add logPath attribute to map
		XAttribute attributePath = factory.createAttributeLiteral(
				PanGuConstants.LOGPATH_ATTRIBUTE, logBuffer.getLogPath(), null);
		attributeMap.put(attributePath.getKey(), attributePath);
		// add timestamp attribute to map
		String timeString = logBuffer.getTimeStamp();
		Date timeStamp = Format.stringToTimeStamp(timeString);
		XAttribute attributeTime = factory.createAttributeTimestamp(
				XTimeExtension.KEY_TIMESTAMP, timeStamp, null);
		attributeMap.put(attributeTime.getKey(), attributeTime);
		currentTimeString = timeString;
		// set event's AttributesMap
		event.setAttributes(attributeMap);
	}

	/**
	 * put event into log
	 * 
	 * @param logBuffer
	 *            the logBuufer that contains the informatino of event
	 * @param event
	 *            the event
	 * @param logCaseIDString
	 *            the caseID of logBuffer
	 */
	private void putEventToLog(LogBufferModified logBuffer, XEvent event) {

		// get caseID for this logBuffer
		String logCaseIDString = logBuffer.getCaseIDString();
		// if map already contains this event's caseID
		if (caseBranchMap.containsKey(logCaseIDString)) {
			int latsetBranchNum = caseBranchMap.get(logCaseIDString);

			// time out, build a new trace with new branch

			if (!caseTraceMap.containsKey(logCaseIDString)) {
				String newCaseID = logCaseIDString + branch11
						+ (latsetBranchNum + 1);
				XTrace traceNew = factory.createTrace();
				// add branch to case map
				caseBranchMap.put(logCaseIDString, latsetBranchNum + 1);
				caseTraceMap.put(logCaseIDString, traceNew);
				XAttributeMap traceAttributeMapNew = factory
						.createAttributeMap();
				XAttribute traceAttributeID = factory.createAttributeLiteral(
						XConceptExtension.KEY_NAME, newCaseID, null);
				traceAttributeMapNew.put(traceAttributeID.getKey(),
						traceAttributeID);
				traceNew.setAttributes(traceAttributeMapNew);
				traceNew.add(event);
				log.add(traceNew);	// 2

				XESConvertorMonitor.instance().updateLastestArrivalMap(
						traceNew, logBuffer.getTimeStamp());

			} else {
				XTrace lastTrace = caseTraceMap.get(logCaseIDString);
				boolean ifTimeOut = XESConvertorMonitor.instance().ifTimeOut(
						logBuffer, lastTrace);
				if (ifTimeOut) {
					String newCaseID = logCaseIDString + branch11
							+ (latsetBranchNum + 1);
					XTrace traceNew = factory.createTrace();
					// add branch to case map
					caseBranchMap.put(logCaseIDString, latsetBranchNum + 1);
					caseTraceMap.put(logCaseIDString, traceNew);
					XAttributeMap traceAttributeMapNew = factory
							.createAttributeMap();
					XAttribute traceAttributeID = factory
							.createAttributeLiteral(XConceptExtension.KEY_NAME,
									newCaseID, null);
					traceAttributeMapNew.put(traceAttributeID.getKey(),
							traceAttributeID);
					traceNew.setAttributes(traceAttributeMapNew);
					traceNew.add(event);
					log.add(traceNew); // 1
					XESConvertorMonitor.instance().updateLastestArrivalMap(
							traceNew, logBuffer.getTimeStamp());
				} else { // not timeout
					lastTrace.add(event);
					XESConvertorMonitor.instance().updateLastestArrivalMap(
							lastTrace, logBuffer.getTimeStamp());
				}
			}

		} else { // do not has CaseID,then build a new trace
			XTrace traceNew = factory.createTrace();
			XAttributeMap traceAttributeMapNew = factory.createAttributeMap();

			String caseIDString = logBuffer.getCaseIDString();
			// add branch to case map
			caseBranchMap.put(caseIDString, 1);
			caseTraceMap.put(caseIDString, traceNew);
			// System.out.println("new caseIDString"+caseIDString);
			// getCaseBranchMap().put(caseIDString, traceNew);
			caseIDString = caseIDString.concat(branch11 + 1);

			XAttribute traceAttributeNew = factory.createAttributeLiteral(
					XConceptExtension.KEY_NAME, caseIDString, null);
			traceAttributeMapNew.put(traceAttributeNew.getKey(),
					traceAttributeNew);
			traceNew.setAttributes(traceAttributeMapNew);

			traceNew.add(event);


			// add new trace to log
			log.add(traceNew); // 3
			XESConvertorMonitor.instance().updateLastestArrivalMap(traceNew,
					logBuffer.getTimeStamp());
		}

		numOfEvent++;
		setTotalEvent(getTotalEvent() + 1);
		clock++;
		if (clock >= PanGuConstants.MAX_EVENT_NUM) {
			clock = 0;
			splitXLog();
		}
	}
	/**
	 * 
	 * 
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	private void splitXLog() {
		if (numOfEvent > PanGuConstants.MUTIPLE_MAX_EVENT_NUM
				* PanGuConstants.MAX_EVENT_NUM) {
			Date currentTime = Format.stringToTimeStamp(currentTimeString); // the

			Iterator<XTrace> iterator = log.iterator();
			List<XTrace> tempXTraceList = new ArrayList<XTrace>();
			while (iterator.hasNext()) {
				XTrace currentTrace = iterator.next();
				String latestTime = XESConvertorMonitor.instance()
						.getLastestArrivalMap().get(currentTrace);
				Date lasterTime = Format.stringToTimeStamp(latestTime);
				// complete trace
				if (Math.abs(currentTime.getTime() - lasterTime.getTime()) > PanGuConstants.TIMEROUT) {
					// if trace not fit //ww				

					logReplace.add(currentTrace);
					XESConvertorMonitor.instance().setNumOfEvent(XESConvertorMonitor
							.instance().getNumOfEvent() + currentTrace.size());
					XESConvertorMonitor.instance().getLastestArrivalMap()
							.remove(currentTrace); // dd

					tempXTraceList.add(currentTrace);
					XAttributeMap map = currentTrace.getAttributes();
					XAttribute tempAttribute = map
							.get(XConceptExtension.KEY_NAME);
					String caseIDValue = ((XAttributeLiteralImpl) tempAttribute)
							.getValue();
					int pos = caseIDValue.lastIndexOf(branch11);
					String caseIDWithoutBranch = caseIDValue.substring(0, pos);
					String branch = caseIDValue
							.substring(pos + branch11.length());
					if (caseBranchMap.containsKey(caseIDWithoutBranch)
							&& caseBranchMap.get(caseIDWithoutBranch)
									.toString().equalsIgnoreCase(branch)) {
						caseTraceMap.remove(caseIDWithoutBranch); // remove
					} 

					if (XESConvertorMonitor.instance().ifExceedMaxEventNum()) {
						if (XESConvertorMonitor.instance().getNumOfEvent()
								- currentTrace.size() != 0) {
							logReplace.remove(currentTrace); // 1
							XESConvertorMonitor.instance().setNumOfEvent(XESConvertorMonitor
									.instance().getNumOfEvent()
									- currentTrace.size()); // 1
							XESConvertorMonitor.instance()
									.getLastestArrivalMap()
									.put(currentTrace, latestTime);
							tempXTraceList.remove(currentTrace);
							caseTraceMap.put(caseIDWithoutBranch, currentTrace);
						} else {
							numOfEvent = numOfEvent - currentTrace.size();
						}
						System.out
								.print("\nsize of events in logReplace before writeToXES: "
										+ +XESConvertorMonitor.instance().getNumOfEvent());
						System.out
								.print("\nsize of events in log before logReplace writeToXES: "
										+ numOfEvent);
						writeToXES(logReplace);
						logReplace = factory.createLog();
						XESConvertorMonitor.instance().setNumOfEvent(0);
						continue;
					} else {			
						numOfEvent = numOfEvent - currentTrace.size();
					}
				}
			}
			log.removeAll(tempXTraceList);
		}

		return;
	}
	/**
	 * 
	 * 
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	public void splitFinalLog() {

		while (numOfEvent > PanGuConstants.MAX_EVENT_NUM) {
			// System.out.println("numOfEvent:"+numOfEvent);
			Iterator<XTrace> iterator = log.iterator();
			List<XTrace> tempXTraceList = new ArrayList<XTrace>();
			if (!iterator.hasNext()) {
				System.out.println("numOFEvent" + numOfEvent);
				System.out.println("!iterator.hasNext() log size:");
				// System.out.println("getLogSize(log)" + getLogSize(log));
			}
			while (iterator.hasNext()) {
				XTrace currentTrace = iterator.next();
				logReplace.add(currentTrace);
				XESConvertorMonitor.instance().setNumOfEvent(XESConvertorMonitor
						.instance().getNumOfEvent() + currentTrace.size());
				tempXTraceList.add(currentTrace);

				if (XESConvertorMonitor.instance().getNumOfEvent() > PanGuConstants.MAX_EVENT_NUM) {

					numOfEvent = numOfEvent - currentTrace.size();
					System.out
							.print("\nsplit final log:size in logReplace before writeToXES: "
									+ XESConvertorMonitor.instance().getNumOfEvent());
					System.out
							.print("\nsplit final log:size in log before logReplace writeToXES: "
									+ numOfEvent);

					writeToXES(logReplace);
					logReplace = factory.createLog();

					XESConvertorMonitor.instance().setNumOfEvent(0);
					break;
				} else {
					numOfEvent = numOfEvent - currentTrace.size();
				}
			}
			log.removeAll(tempXTraceList);
		}
	}

	/**
	 * write log to xes file() function for test
	 */
	private void writeToXESLocal(XLog writeLog) {
		// wirteLog is empty
		if (writeLog.size() == 0) {
			return;
		}
		// get the size of events in writeLog
		System.out.print("\nwrite to XES");
		try {
			String name = resultFilePath + "_" + xesBranch2 + ".xes";
			File sFile = new File("F:/" + name);

			if (sFile.exists()) {
				sFile.delete();
			}
			try {
				sFile.createNewFile();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			XesXmlSerializer xstream = new XesXmlSerializer();
			OutputStream oStream = new BufferedOutputStream(
					new FileOutputStream(sFile));
			xstream.serialize(writeLog, oStream);

			xesBranch2++;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * write log to xes file
	 */
	private void writeToXES(XLog writeLog) {
		// wirteLog is empty
		if (writeLog.size() == 0) {
			System.out.print("\nwriteLog.size() == 0");
			return;
		}
		// get the size of events in writeLog
		System.out.print("\nwrite to XES");
		PropertiesReaderServices x1 = PropertiesReaderServicesImpl.instance();
		try {
			String name = resultFilePath + "_" + xesBranch2 + ".xes";

			File sFile = new File(x1.getProperties("XES_WRITE_PATH") + name);

			if (sFile.exists()) {
				sFile.delete();
			}
			try {
				sFile.createNewFile();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			XesXmlSerializer xstream = new XesXmlSerializer();
			OutputStream oStream = new BufferedOutputStream(
					new FileOutputStream(sFile));
			xstream.serialize(writeLog, oStream);
			oStream.close();

			SAXBuilder builder = new SAXBuilder();
			Document doc = builder.build(sFile);
			XMLOutputter outputter = new XMLOutputter();
			String xesString = outputter.outputString(doc);

			XESHelper xesh = new XESHelper();
			Date currentTime = new Date();

			DbXES dbxes = new DbXES(Integer.toString(xesBranch2),
					resultFilePath, xesString, currentTime.toString(), classify);
			xesh.saveXES(dbxes);

			xesBranch2++;
		} catch (Exception e) {
			e.printStackTrace();
		}


	}
	/**
	 * 
	 * @return
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	public LogBufferModified getTestLogBuffer() {
		return testLogBuffer;
	}
	/**
	 * 
	 * @param logBuffer
	 * logBuffer
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	public void setTestLogBuffer(LogBufferModified logBuffer) {
		this.testLogBuffer = logBuffer;
	}
	/**
	 * 
	 * @return
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	public XLog getLog() {
		return log;
	}
	/**
	 * 
	 * @param log
	 * log
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	public void setLog(XLog log) {
		this.log = log;
	}
	/**
	 * 
	 * @param logL
	 * @return
	 * @author fenyo rome
	 * @date 2013-4-26
	 */
	private int getLogSize(XLog logL) {
		int events = 0;
		XLogInfo info = null;
		info = XLogInfoFactory.createLogInfo(logL);
		events += info.getNumberOfEvents();
		return events;
	}

	/**
	 * @return the totalEvent
	 */
	public int getTotalEvent() {
		return totalEvent;
	}

	/**
	 * @param totalEvent
	 *            the totalEvent to set
	 */
	public void setTotalEvent(int totalEvent) {
		this.totalEvent = totalEvent;
	}

	/**
	 * @return the caseBranchMap
	 */
	public Hashtable<String, Integer> getCaseBranchMap() {
		return caseBranchMap;
	}

	/**
	 * @param caseBranchMap
	 *            the caseBranchMap to set
	 */
	public void setCaseBranchMap(Hashtable<String, Integer> caseBranchMap) {
		this.caseBranchMap = caseBranchMap;
	}
	public static void main(String [] args) {
		System.out.println("begin");
		XESConvertService xesconvertor = XESConvertServiceImp.instance();
		xesconvertor.setReadFilePath("E:\\logcenter.201302100001.log");
		WebConfigReadService configService = WebConfigReadServiceImpl.instance();
		configService.setPatternName("generalclick2_1");
		configService.setVersionName("version2.0");
		configService.config();
		LogCleanConfigReadService logcleanconfigservice = LogCleanConfigReadServiceImpl.instance();
		logcleanconfigservice.setNoiseflag(1); // 说明已经选择noise文件
		logcleanconfigservice.setNoiseFileName("generalclick2_1");
		xesconvertor.setResultFile("goodxx_guofen5");
		xesconvertor.setClassify("page");
		xesconvertor.convert();
		
	}
}
